#include "TrueText/Config.h"
#include "TrueText/Stream.h"
#include "StreamImpl.h"

namespace {

class MemoryStreamImpl : public TrueText::StreamImpl
{
public:
	MemoryStreamImpl(void* ptr, size_t sz)
		: ptr(ptr)
		, sz(sz)
	{ }
public:
	virtual FT_Stream GetStream()
	{
		memset(&streamRec, 0, sizeof(FT_StreamRec));
		streamRec.base = reinterpret_cast<unsigned char*>(ptr);
		streamRec.size = sz;

		return &streamRec;
	}
private:
	FT_StreamRec streamRec;
	void* ptr;
	size_t sz;
};

}

namespace TrueText {

class CachingMemoryStreamImpl : public TrueText::StreamImpl
{
public:
	CachingMemoryStreamImpl(void* srcPtr, size_t sz)
		: sz(sz)
	{
		ptr = new char[sz];
		memcpy(ptr, srcPtr, sz);
	}

	CachingMemoryStreamImpl(size_t sz)
		: sz(sz)
	{
		ptr = new char[sz];
	}

	void* GetBuffer()
	{
		return ptr;
	}

	~CachingMemoryStreamImpl()
	{
		if (ptr)
			delete[] ptr;
	}
public:
	virtual FT_Stream GetStream()
	{
		memset(&streamRec, 0, sizeof(FT_StreamRec));
		streamRec.base = reinterpret_cast<unsigned char*>(ptr);
		streamRec.size = sz;

		return &streamRec;
	}
private:
	FT_StreamRec streamRec;
	char* ptr;
	size_t sz;
};

MemoryStream::MemoryStream(void* ptr, size_t sz)
{ 
	impl.reset(new MemoryStreamImpl(ptr, sz));
}

MemoryStream::~MemoryStream()
{ }

StreamImpl* MemoryStream::getImpl()
{
	return impl.get();
}

CachingMemoryStream::CachingMemoryStream(void* ptr, size_t sz)
{
	impl.reset(new CachingMemoryStreamImpl(ptr, sz));
}

CachingMemoryStream::CachingMemoryStream(size_t sz)
{
	impl.reset(new CachingMemoryStreamImpl(sz));
}

void* CachingMemoryStream::GetBuffer()
{
	return impl->GetBuffer();
}

StreamImpl* CachingMemoryStream::getImpl()
{
	return impl.get();
}

CachingMemoryStream::~CachingMemoryStream()
{
}

}